functor X86Asmize (S : X86ASMIZE_STRUCTS) : X86ASMIZE =
struct
  open S
  
  structure X86Asm = X86Asm
  structure Machine = Machine
  
  val error = ErrorMsg.error
  
  val tag = false
  fun debugPrint s =
      if tag
      then print s
      else ()      
  
  local open X86Asm
  in structure XC = Cmd
     structure XR = Register
     structure XO = Operand
     structure XI = Ins
     structure XK = Block
     structure XF = Function
     structure XP = Program
  end
  
  local open Machine
  in structure L = Location
     structure B = Binop
     structure R = Register
     structure O = Operand
     structure K = Block
     structure S = Structs
     structure J = Transfer
     structure M = Stm
     structure F = Function
     structure P = Program
     structure Intl = Intl
     structure Id = Id
     structure T = Types
  end
  
  fun printList (n, l, info) =
      let val _ = debugPrint (String.concat ["\nthe ", info, " of ", Id.toString n, " is:\n"])
          val _ = List.app debugPrint (List.map Id.toString l)
      in  ()
      end


  val {get = getLocal, set = setLocal, destroy = destroyLocal, ...} :
      {get : Id.t -> (XO.t option), set : Id.t * (XO.t option) -> unit, destroy : unit -> unit} =
      Property.destGetSetOnce (Id.plist, Property.initConst NONE)

  fun transReg r =
      case r
       of R.eax => XR.eax
        | R.ebx => XR.ebx
        | R.ecx => XR.ecx
        | R.edx => XR.edx
        | R.esi => XR.esi
        | R.edi => XR.edi
        | R.ebp => XR.ebp
        | R.esp => XR.esp
        
  fun transOperand v = 
      case v
       of O.OpVoid => XO.OpVoid
        | O.IntNum i => XO.IntNum i
        | O.Var {id, ty, ...} =>
          let val newOp = getLocal id
          in  case newOp 
               of NONE => XO.Label {id = id, ty = ty}
                | SOME s => s
          end
        | O.True => XO.True
        | O.False => XO.False
        | O.Null => XO.Null
        | O.Mem {id, ty, ...} => 
          let val newOp = getLocal id
          in  case newOp
               of NONE => raise Fail (String.concat ["Compiler bug, non-local variable: ", Id.toString id])
                | SOME s => s
          end
        | O.Reg {reg, ty} => XO.Reg {reg = transReg reg, ty = ty}

  fun transStm s = 
      case s
       of M.Assign {line, dest, src, ty} =>
          let val newSrc = transOperand src
              val newDest = transOperand dest
          in (case src
               of O.Mem {id, ty, ...} =>
                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc, dest = XO.Reg {reg = XR.ebx, ty = T.Pointt ty}}]
                  in (case dest
                       of O.Mem _ => 
                          ins1 @
                          [XI.I {cmd = XC.Mov, 
                                 src = XO.Rmem {off = Intl.fromInt 0, reg = XR.ebx, ty = ty}, 
                                 dest = XO.Reg {reg = XR.eax, ty = ty}},
                           XI.I {cmd = XC.Mov, src = newDest, dest = XO.Reg {reg = XR.ebx, ty = T.Pointt ty}},
                           XI.I {cmd = XC.Mov, 
                                 src = XO.Reg {reg = XR.eax, ty = ty},
                                 dest = XO.Rmem {off = Intl.fromInt 0, reg = XR.ebx, ty = ty}}]
                        | O.Var _ =>
                          ins1 @
                          [XI.I {cmd = XC.Mov, 
                                 src = XO.Rmem {off = Intl.fromInt 0, reg = XR.ebx, ty = ty}, 
                                 dest = XO.Reg {reg = XR.eax, ty = ty}},
                           XI.I {cmd = XC.Mov,
                                 src = XO.Reg {reg = XR.eax, ty = ty},
                                 dest = newDest}]
                        | O.Reg _ =>
                          ins1 @
                          [XI.I {cmd = XC.Mov, 
                                 src = XO.Rmem {off = Intl.fromInt 0, reg = XR.ebx, ty = ty},
                                 dest = newDest}]
                        | _ => raise Fail "Compiler bug: Invalid dest")
                  end
                | O.Var _ =>
                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc, dest = XO.Reg {reg = XR.eax, ty = ty}}]
                  in  case dest
                       of O.Mem _ =>
                          ins1 @
                          [XI.I {cmd = XC.Mov, src = newDest, dest = XO.Reg {reg = XR.ebx, ty = T.Pointt ty}},
                           XI.I {cmd = XC.Mov, 
                                 src = XO.Reg {reg = XR.eax, ty = ty}, 
                                 dest = XO.Rmem {off = Intl.fromInt 0, reg = XR.ebx, ty = ty}}] 
                        | O.Var _ => ins1 @ [XI.I {cmd = XC.Mov, 
                                                   src = XO.Reg {reg = XR.eax, ty = ty}, 
                                                   dest = newDest}]
                        | O.Reg _ => [XI.I {cmd = XC.Mov, src = newSrc, dest = newDest}]
                        | _ => raise Fail "Compiler bug: Invalid dest"
                  end
                | O.OpVoid => raise Fail "Compiler bug: Invalid src"
                | _ => 
                  let val ins = [XI.I {cmd = XC.Mov, src = newSrc, dest = newDest}]
                  in  case dest
                       of O.Mem _ => 
                          [XI.I {cmd = XC.Mov, src = newDest, dest = XO.Reg {reg = XR.ebx, ty = T.Pointt ty}},
                           XI.I {cmd = XC.Mov, src = newSrc, 
                                 dest = XO.Rmem {off = Intl.fromInt 0, reg = XR.ebx, ty = ty}}]
                        | O.Var _ => ins
                        | O.Reg _ => ins
                        | _ => raise Fail "Compiler bug: Invalid dest"
                  end)
          end
        | M.AssignExp {line, dest, bop, src, ty} =>
          let val src1 = List.hd src
              val newSrc1 = transOperand src1
              val src2 = case (List.tl src)
                          of [] => O.OpVoid
                           | x :: xs => x
              val newSrc2 = transOperand src2
              val newDest = transOperand dest
              val Ebx = XO.Reg {reg = XR.ebx, ty = T.Pointt ty}
              val getEbx = XO.Rmem {off = Intl.fromInt 0, reg = XR.ebx, ty = ty}
              val Esi = XO.Reg {reg = XR.esi, ty = T.Pointt ty}
              val getEsi = XO.Rmem {off = Intl.fromInt 0, reg = XR.esi, ty = ty}
              val Eax = XO.Reg {reg = XR.eax, ty = ty}
          in  case bop
               of B.Plus =>
                  let val _ = ()      
                  in  case dest
                       of O.Mem _ =>
                          let val insLast = [XI.I {cmd = XC.Mov, src = newDest, dest = Ebx},
                                             XI.I {cmd = XC.Mov, src = Eax, dest = getEbx}]
                          in  case src1
                               of O.Mem _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Ebx},
                                                  XI.I {cmd = XC.Mov, src = getEbx, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Add, src = getEbx, dest = Eax}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Add, src = newSrc2, dest = Eax}]@
                                               insLast
                                  end
                                | _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Add, src = getEbx, dest = Eax}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Add, src = newSrc2, dest = Eax}]@
                                               insLast
                                  end
                          end
                        | _ =>
                          let val insLast = [XI.I {cmd = XC.Mov, src = Eax, dest = newDest}]
                          in  case src1
                               of O.Mem _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Ebx},
                                                  XI.I {cmd = XC.Mov, src = getEbx, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Add, src = getEbx, dest = Eax}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Add, src = newSrc2, dest = Eax}]@
                                               insLast
                                  end
                                | _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Add, src = getEbx, dest = Eax}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Add, src = newSrc2, dest = Eax}]@
                                               insLast
                                  end
                          end                
                  end
                | B.Minus => 
                  let val _ = ()      
                  in  case dest
                       of O.Mem _ =>
                          let val insLast = [XI.I {cmd = XC.Mov, src = newDest, dest = Ebx},
                                             XI.I {cmd = XC.Mov, src = Eax, dest = getEbx}]
                          in  case src1
                               of O.Mem _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Ebx},
                                                  XI.I {cmd = XC.Mov, src = getEbx, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Sub, src = getEbx, dest = Eax}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Sub, src = newSrc2, dest = Eax}]@
                                               insLast
                                  end
                                | _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Sub, src = getEbx, dest = Eax}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Sub, src = newSrc2, dest = Eax}]@
                                               insLast
                                  end
                          end
                        | _ =>
                          let val insLast = [XI.I {cmd = XC.Mov, src = Eax, dest = newDest}]
                          in  case src1
                               of O.Mem _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Ebx},
                                                  XI.I {cmd = XC.Mov, src = getEbx, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Sub, src = getEbx, dest = Eax}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Sub, src = newSrc2, dest = Eax}]@
                                               insLast
                                  end
                                | _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Sub, src = getEbx, dest = Eax}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Sub, src = newSrc2, dest = Eax}]@
                                               insLast
                                  end
                          end                
                  end
                | B.Times => 
                  let val _ = ()      
                  in  case dest
                       of O.Mem _ =>
                          let val insLast = [XI.I {cmd = XC.Mov, src = newDest, dest = Ebx},
                                             XI.I {cmd = XC.Mov, src = Eax, dest = getEbx}]
                          in  case src1
                               of O.Mem _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Ebx},
                                                  XI.I {cmd = XC.Mov, src = getEbx, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Mul, src = getEbx, dest = Eax}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Mul, src = newSrc2, dest = Eax}]@
                                               insLast
                                  end
                                | _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Mul, src = getEbx, dest = Eax}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Mul, src = newSrc2, dest = Eax}]@
                                               insLast
                                  end
                          end
                        | _ =>
                          let val insLast = [XI.I {cmd = XC.Mov, src = Eax, dest = newDest}]
                          in  case src1
                               of O.Mem _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Ebx},
                                                  XI.I {cmd = XC.Mov, src = getEbx, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Mul, src = getEbx, dest = Eax}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Mul, src = newSrc2, dest = Eax}]@
                                               insLast
                                  end
                                | _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Mul, src = getEbx, dest = Eax}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Mul, src = newSrc2, dest = Eax}]@
                                               insLast
                                  end
                          end                
                  end
               
                | B.Divide => 
                  let val _ = ()      
                  in  case dest
                       of O.Mem _ =>
                          let val insLast = [XI.I {cmd = XC.Mov, src = newDest, dest = Ebx},
                                             XI.I {cmd = XC.Mov, src = Eax, dest = getEbx}]
                          in  case src1
                               of O.Mem _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Ebx},
                                                  XI.I {cmd = XC.Mov, src = getEbx, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Div, src = getEbx, dest = XO.OpVoid}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Div, src = newSrc2, dest = XO.OpVoid}]@
                                               insLast
                                  end
                                | _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Div, src = getEbx, dest = XO.OpVoid}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Div, src = newSrc2, dest = XO.OpVoid}]@
                                               insLast
                                  end
                          end
                        | _ =>
                          let val insLast = [XI.I {cmd = XC.Mov, src = Eax, dest = newDest}]
                          in  case src1
                               of O.Mem _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Ebx},
                                                  XI.I {cmd = XC.Mov, src = getEbx, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Div, src = getEbx, dest = XO.OpVoid}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Div, src = newSrc2, dest = XO.OpVoid}]@
                                               insLast
                                  end
                                | _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Div, src = getEbx, dest = XO.OpVoid}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Div, src = newSrc2, dest = XO.OpVoid}]@
                                               insLast
                                  end
                          end                
                  end               
                | B.Modus => 
                  let val Edx = XO.Reg {reg = XR.edx, ty = ty}      
                  in  case dest
                       of O.Mem _ =>
                          let val insLast = [XI.I {cmd = XC.Mov, src = newDest, dest = Ebx},
                                             XI.I {cmd = XC.Mov, src = Edx, dest = getEbx}]
                          in  case src1
                               of O.Mem _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Ebx},
                                                  XI.I {cmd = XC.Mov, src = getEbx, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Div, src = getEbx, dest = XO.OpVoid}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Div, src = newSrc2, dest = XO.OpVoid}]@
                                               insLast
                                  end
                                | _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Div, src = getEbx, dest = XO.OpVoid}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Div, src = newSrc2, dest = XO.OpVoid}]@
                                               insLast
                                  end
                          end
                        | _ =>
                          let val insLast = [XI.I {cmd = XC.Mov, src = Edx, dest = newDest}]
                          in  case src1
                               of O.Mem _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Ebx},
                                                  XI.I {cmd = XC.Mov, src = getEbx, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Div, src = getEbx, dest = XO.OpVoid}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Div, src = newSrc2, dest = XO.OpVoid}]@
                                               insLast
                                  end
                                | _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Div, src = getEbx, dest = XO.OpVoid}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Div, src = newSrc2, dest = XO.OpVoid}]@
                                               insLast
                                  end
                          end                
                  end
                | B.Not => 
                  let val allOne = XO.IntNum (Intl.fromInt (~1))    
                  in  case dest
                       of O.Mem _ =>
                          let val insLast = [XI.I {cmd = XC.Mov, src = newDest, dest = Ebx},
                                             XI.I {cmd = XC.Mov, src = Eax, dest = getEbx}]
                          in  case src1
                               of O.Mem _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Ebx},
                                                  XI.I {cmd = XC.Mov, src = getEbx, dest = Eax}]
                                  in  ins1 @
                                      [XI.I {cmd = XC.Not, src = Eax, dest = XO.OpVoid},
                                       XI.I {cmd = XC.Xor, src = allOne, dest = Eax},
                                       XI.I {cmd = XC.Sete, src = Eax, dest = XO.OpVoid}]@
                                      insLast
                                  end
                                | _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Eax}]
                                  in  ins1 @
                                      [XI.I {cmd = XC.Not, src = Eax, dest = XO.OpVoid},
                                       XI.I {cmd = XC.Xor, src = allOne, dest = Eax},
                                       XI.I {cmd = XC.Sete, src = Eax, dest = XO.OpVoid}]@
                                      insLast
                                  end
                          end
                        | _ =>
                          let val insLast = [XI.I {cmd = XC.Mov, src = Eax, dest = newDest}]
                          in  case src1
                               of O.Mem _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Ebx},
                                                  XI.I {cmd = XC.Mov, src = getEbx, dest = Eax}]
                                  in  ins1 @
                                      [XI.I {cmd = XC.Not, src = Eax, dest = XO.OpVoid},
                                       XI.I {cmd = XC.Xor, src = allOne, dest = Eax},
                                       XI.I {cmd = XC.Sete, src = Eax, dest = XO.OpVoid}]@
                                      insLast
                                  end
                                | _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Eax}]
                                  in  ins1 @
                                      [XI.I {cmd = XC.Not, src = Eax, dest = XO.OpVoid},
                                       XI.I {cmd = XC.Xor, src = allOne, dest = Eax},
                                       XI.I {cmd = XC.Sete, src = Eax, dest = XO.OpVoid}]@
                                      insLast
                                  end
                          end                
                  end
                | B.And => 
                let val _ = ()      
                  in  case dest
                       of O.Mem _ =>
                          let val insLast = [XI.I {cmd = XC.Mov, src = newDest, dest = Ebx},
                                             XI.I {cmd = XC.Mov, src = Eax, dest = getEbx}]
                          in  case src1
                               of O.Mem _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Ebx},
                                                  XI.I {cmd = XC.Mov, src = getEbx, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.And, src = getEbx, dest = Eax}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.And, src = newSrc2, dest = Eax}]@
                                               insLast
                                  end
                                | _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.And, src = getEbx, dest = Eax}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.And, src = newSrc2, dest = Eax}]@
                                               insLast
                                  end
                          end
                        | _ =>
                          let val insLast = [XI.I {cmd = XC.Mov, src = Eax, dest = newDest}]
                          in  case src1
                               of O.Mem _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Ebx},
                                                  XI.I {cmd = XC.Mov, src = getEbx, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.And, src = getEbx, dest = Eax}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.And, src = newSrc2, dest = Eax}]@
                                               insLast
                                  end
                                | _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.And, src = getEbx, dest = Eax}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.And, src = newSrc2, dest = Eax}]@
                                               insLast
                                  end
                          end                
                  end
                | B.Or => 
                let val _ = ()      
                  in  case dest
                       of O.Mem _ =>
                          let val insLast = [XI.I {cmd = XC.Mov, src = newDest, dest = Ebx},
                                             XI.I {cmd = XC.Mov, src = Eax, dest = getEbx}]
                          in  case src1
                               of O.Mem _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Ebx},
                                                  XI.I {cmd = XC.Mov, src = getEbx, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Or, src = getEbx, dest = Eax}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Or, src = newSrc2, dest = Eax}]@
                                               insLast
                                  end
                                | _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Or, src = getEbx, dest = Eax}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Or, src = newSrc2, dest = Eax}]@
                                               insLast
                                  end
                          end
                        | _ =>
                          let val insLast = [XI.I {cmd = XC.Mov, src = Eax, dest = newDest}]
                          in  case src1
                               of O.Mem _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Ebx},
                                                  XI.I {cmd = XC.Mov, src = getEbx, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Or, src = getEbx, dest = Eax}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Or, src = newSrc2, dest = Eax}]@
                                               insLast
                                  end
                                | _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Or, src = getEbx, dest = Eax}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Or, src = newSrc2, dest = Eax}]@
                                               insLast
                                  end
                          end                
                  end
                | B.Eq =>
                  let val _ = ()
                  in  case dest
                       of O.Mem _ =>
                          let val insLast = [XI.I {cmd = XC.Mov, src = newDest, dest = Ebx},
                                             XI.I {cmd = XC.Mov, src = Eax, dest = getEbx}]
                          in  case src1
                               of O.Mem _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Ebx},
                                                  XI.I {cmd = XC.Mov, src = getEbx, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Cmp, src = getEbx, dest = Eax},
                                           XI.I {cmd = XC.Sete, src = Eax, dest = XO.OpVoid}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Cmp, src = newSrc2, dest = Eax},
                                                XI.I {cmd = XC.Sete, src = Eax, dest = XO.OpVoid}]@
                                               insLast
                                  end
                                | _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Cmp, src = getEbx, dest = Eax},
                                           XI.I {cmd = XC.Sete, src = Eax, dest = XO.OpVoid}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Cmp, src = newSrc2, dest = Eax},
                                                XI.I {cmd = XC.Sete, src = Eax, dest = XO.OpVoid}]@
                                               insLast
                                  end
                          end
                        | _ =>
                          let val insLast = [XI.I {cmd = XC.Mov, src = Eax, dest = newDest}]
                          in  case src1
                               of O.Mem _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Ebx},
                                                  XI.I {cmd = XC.Mov, src = getEbx, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Cmp, src = getEbx, dest = Eax},
                                           XI.I {cmd = XC.Sete, src = Eax, dest = XO.OpVoid}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Cmp, src = newSrc2, dest = Eax},
                                                XI.I {cmd = XC.Sete, src = Eax, dest = XO.OpVoid}]@
                                               insLast
                                  end
                                | _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Cmp, src = getEbx, dest = Eax},
                                           XI.I {cmd = XC.Sete, src = Eax, dest = XO.OpVoid}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Cmp, src = newSrc2, dest = Eax},
                                                XI.I {cmd = XC.Sete, src = Eax, dest = XO.OpVoid}]@
                                               insLast
                                  end
                          end   
                  end
                | B.Ne =>
                  let val _ = ()
                  in  case dest
                       of O.Mem _ =>
                          let val insLast = [XI.I {cmd = XC.Mov, src = newDest, dest = Ebx},
                                             XI.I {cmd = XC.Mov, src = Eax, dest = getEbx}]
                          in  case src1
                               of O.Mem _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Ebx},
                                                  XI.I {cmd = XC.Mov, src = getEbx, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Cmp, src = getEbx, dest = Eax},
                                           XI.I {cmd = XC.Setne, src = Eax, dest = XO.OpVoid}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Cmp, src = newSrc2, dest = Eax},
                                                XI.I {cmd = XC.Setne, src = Eax, dest = XO.OpVoid}]@
                                               insLast
                                  end
                                | _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Cmp, src = getEbx, dest = Eax},
                                           XI.I {cmd = XC.Setne, src = Eax, dest = XO.OpVoid}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Cmp, src = newSrc2, dest = Eax},
                                                XI.I {cmd = XC.Setne, src = Eax, dest = XO.OpVoid}]@
                                               insLast
                                  end
                          end
                        | _ =>
                          let val insLast = [XI.I {cmd = XC.Mov, src = Eax, dest = newDest}]
                          in  case src1
                               of O.Mem _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Ebx},
                                                  XI.I {cmd = XC.Mov, src = getEbx, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Cmp, src = getEbx, dest = Eax},
                                           XI.I {cmd = XC.Setne, src = Eax, dest = XO.OpVoid}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Cmp, src = newSrc2, dest = Eax},
                                                XI.I {cmd = XC.Setne, src = Eax, dest = XO.OpVoid}]@
                                               insLast
                                  end
                                | _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Cmp, src = getEbx, dest = Eax},
                                           XI.I {cmd = XC.Setne, src = Eax, dest = XO.OpVoid}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Cmp, src = newSrc2, dest = Eax},
                                                XI.I {cmd = XC.Setne, src = Eax, dest = XO.OpVoid}]@
                                               insLast
                                  end
                          end   
                  end
                | B.Gt => 
                  let val _ = ()
                  in  case dest
                       of O.Mem _ =>
                          let val insLast = [XI.I {cmd = XC.Mov, src = newDest, dest = Ebx},
                                             XI.I {cmd = XC.Mov, src = Eax, dest = getEbx}]
                          in  case src1
                               of O.Mem _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Ebx},
                                                  XI.I {cmd = XC.Mov, src = getEbx, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Cmp, src = getEbx, dest = Eax},
                                           XI.I {cmd = XC.Setg, src = Eax, dest = XO.OpVoid}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Cmp, src = newSrc2, dest = Eax},
                                                XI.I {cmd = XC.Setg, src = Eax, dest = XO.OpVoid}]@
                                               insLast
                                  end
                                | _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Cmp, src = getEbx, dest = Eax},
                                           XI.I {cmd = XC.Setg, src = Eax, dest = XO.OpVoid}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Cmp, src = newSrc2, dest = Eax},
                                                XI.I {cmd = XC.Setg, src = Eax, dest = XO.OpVoid}]@
                                               insLast
                                  end
                          end
                        | _ =>
                          let val insLast = [XI.I {cmd = XC.Mov, src = Eax, dest = newDest}]
                          in  case src1
                               of O.Mem _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Ebx},
                                                  XI.I {cmd = XC.Mov, src = getEbx, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Cmp, src = getEbx, dest = Eax},
                                           XI.I {cmd = XC.Setg, src = Eax, dest = XO.OpVoid}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Cmp, src = newSrc2, dest = Eax},
                                                XI.I {cmd = XC.Setg, src = Eax, dest = XO.OpVoid}]@
                                               insLast
                                  end
                                | _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Cmp, src = getEbx, dest = Eax},
                                           XI.I {cmd = XC.Setg, src = Eax, dest = XO.OpVoid}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Cmp, src = newSrc2, dest = Eax},
                                                XI.I {cmd = XC.Setg, src = Eax, dest = XO.OpVoid}]@
                                               insLast
                                  end
                          end   
                  end
                | B.Ge =>
                  let val _ = ()
                  in  case dest
                       of O.Mem _ =>
                          let val insLast = [XI.I {cmd = XC.Mov, src = newDest, dest = Ebx},
                                             XI.I {cmd = XC.Mov, src = Eax, dest = getEbx}]
                          in  case src1
                               of O.Mem _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Ebx},
                                                  XI.I {cmd = XC.Mov, src = getEbx, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Cmp, src = getEbx, dest = Eax},
                                           XI.I {cmd = XC.Setge, src = Eax, dest = XO.OpVoid}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Cmp, src = newSrc2, dest = Eax},
                                                XI.I {cmd = XC.Setge, src = Eax, dest = XO.OpVoid}]@
                                               insLast
                                  end
                                | _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Cmp, src = getEbx, dest = Eax},
                                           XI.I {cmd = XC.Setge, src = Eax, dest = XO.OpVoid}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Cmp, src = newSrc2, dest = Eax},
                                                XI.I {cmd = XC.Setge, src = Eax, dest = XO.OpVoid}]@
                                               insLast
                                  end
                          end
                        | _ =>
                          let val insLast = [XI.I {cmd = XC.Mov, src = Eax, dest = newDest}]
                          in  case src1
                               of O.Mem _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Ebx},
                                                  XI.I {cmd = XC.Mov, src = getEbx, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Cmp, src = getEbx, dest = Eax},
                                           XI.I {cmd = XC.Setge, src = Eax, dest = XO.OpVoid}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Cmp, src = newSrc2, dest = Eax},
                                                XI.I {cmd = XC.Setge, src = Eax, dest = XO.OpVoid}]@
                                               insLast
                                  end
                                | _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Cmp, src = getEbx, dest = Eax},
                                           XI.I {cmd = XC.Setge, src = Eax, dest = XO.OpVoid}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Cmp, src = newSrc2, dest = Eax},
                                                XI.I {cmd = XC.Setge, src = Eax, dest = XO.OpVoid}]@
                                               insLast
                                  end
                          end   
                  end
                | B.Lt => 
                let val _ = ()
                  in  case dest
                       of O.Mem _ =>
                          let val insLast = [XI.I {cmd = XC.Mov, src = newDest, dest = Ebx},
                                             XI.I {cmd = XC.Mov, src = Eax, dest = getEbx}]
                          in  case src1
                               of O.Mem _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Ebx},
                                                  XI.I {cmd = XC.Mov, src = getEbx, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Cmp, src = getEbx, dest = Eax},
                                           XI.I {cmd = XC.Setl, src = Eax, dest = XO.OpVoid}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Cmp, src = newSrc2, dest = Eax},
                                                XI.I {cmd = XC.Setl, src = Eax, dest = XO.OpVoid}]@
                                               insLast
                                  end
                                | _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Cmp, src = getEbx, dest = Eax},
                                           XI.I {cmd = XC.Setl, src = Eax, dest = XO.OpVoid}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Cmp, src = newSrc2, dest = Eax},
                                                XI.I {cmd = XC.Setl, src = Eax, dest = XO.OpVoid}]@
                                               insLast
                                  end
                          end
                        | _ =>
                          let val insLast = [XI.I {cmd = XC.Mov, src = Eax, dest = newDest}]
                          in  case src1
                               of O.Mem _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Ebx},
                                                  XI.I {cmd = XC.Mov, src = getEbx, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Cmp, src = getEbx, dest = Eax},
                                           XI.I {cmd = XC.Setl, src = Eax, dest = XO.OpVoid}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Cmp, src = newSrc2, dest = Eax},
                                                XI.I {cmd = XC.Setl, src = Eax, dest = XO.OpVoid}]@
                                               insLast
                                  end
                                | _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Cmp, src = getEbx, dest = Eax},
                                           XI.I {cmd = XC.Setl, src = Eax, dest = XO.OpVoid}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Cmp, src = newSrc2, dest = Eax},
                                                XI.I {cmd = XC.Setl, src = Eax, dest = XO.OpVoid}]@
                                               insLast
                                  end
                          end   
                  end
                | B.Le => 
                let val _ = ()
                  in  case dest
                       of O.Mem _ =>
                          let val insLast = [XI.I {cmd = XC.Mov, src = newDest, dest = Ebx},
                                             XI.I {cmd = XC.Mov, src = Eax, dest = getEbx}]
                          in  case src1
                               of O.Mem _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Ebx},
                                                  XI.I {cmd = XC.Mov, src = getEbx, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Cmp, src = getEbx, dest = Eax},
                                           XI.I {cmd = XC.Setle, src = Eax, dest = XO.OpVoid}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Cmp, src = newSrc2, dest = Eax},
                                                XI.I {cmd = XC.Setle, src = Eax, dest = XO.OpVoid}]@
                                               insLast
                                  end
                                | _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Cmp, src = getEbx, dest = Eax},
                                           XI.I {cmd = XC.Setle, src = Eax, dest = XO.OpVoid}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Cmp, src = newSrc2, dest = Eax},
                                                XI.I {cmd = XC.Setle, src = Eax, dest = XO.OpVoid}]@
                                               insLast
                                  end
                          end
                        | _ =>
                          let val insLast = [XI.I {cmd = XC.Mov, src = Eax, dest = newDest}]
                          in  case src1
                               of O.Mem _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Ebx},
                                                  XI.I {cmd = XC.Mov, src = getEbx, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Cmp, src = getEbx, dest = Eax},
                                           XI.I {cmd = XC.Setle, src = Eax, dest = XO.OpVoid}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Cmp, src = newSrc2, dest = Eax},
                                                XI.I {cmd = XC.Setle, src = Eax, dest = XO.OpVoid}]@
                                               insLast
                                  end
                                | _ =>
                                  let val ins1 = [XI.I {cmd = XC.Mov, src = newSrc1, dest = Eax}]
                                  in  case src2
                                       of O.Mem _ => 
                                          ins1 @
                                          [XI.I {cmd = XC.Mov, src = newSrc2, dest = Ebx},
                                           XI.I {cmd = XC.Cmp, src = getEbx, dest = Eax},
                                           XI.I {cmd = XC.Setle, src = Eax, dest = XO.OpVoid}] @
                                          insLast
                                        | _ => ins1 @
                                               [XI.I {cmd = XC.Cmp, src = newSrc2, dest = Eax},
                                                XI.I {cmd = XC.Setle, src = Eax, dest = XO.OpVoid}]@
                                               insLast
                                  end
                          end   
                  end
                
          end
        | M.Call {line, fid, src, ty} =>
          let val newSrc = List.rev src
              fun ArgToPush s =
                  let val newA = transOperand s
                      val Ebx = XO.Reg {reg = XR.ebx, ty = T.Voidt}
                      val getEbx = XO.Rmem {off = Intl.fromInt 0, reg = XR.ebx, ty = T.Voidt}
                  in  case s
                       of O.Mem _ => 
                          [XI.I {cmd = XC.Mov, src = newA, dest = Ebx},
                           XI.I {cmd = XC.Push, src = getEbx, dest = XO.OpVoid}]
                        | _ => [XI.I {cmd = XC.Push, src = newA, dest = XO.OpVoid}]
                  end
              val push = List.concat (List.map ArgToPush newSrc)
              val sizeSrc = (List.length src) * 4
              val Esp = XO.Reg {reg = XR.esp, ty = T.Voidt}
              val push = push @ [XI.I {cmd = XC.Call, src = XO.Label {id = fid, ty = ty}, dest = XO.OpVoid},
                                 XI.I {cmd = XC.Add, src = XO.IntNum (Intl.fromInt sizeSrc), dest = Esp}]
          in  push
          end
        
        | M.Alloc {line, fid, ty} =>
          let val size = Intl.fromInt ((T.size ty) * 4)
              val push = XI.I {cmd = XC.Push, src = XO.IntNum size, dest = XO.OpVoid}
              val push = push :: [XI.I {cmd = XC.Call, src = XO.Label {id = fid, ty = T.Pointt ty}, dest = XO.OpVoid}]
              val Esp = XO.Reg {reg = XR.esp, ty = T.Voidt}
              val push = push @ [XI.I {cmd = XC.Add, src = XO.IntNum (Intl.fromInt 4), dest = Esp}]
          in  push
          end
          
  fun transTransfer (j, exit, rettype) = 
      case j
       of J.Jump {line, label} => [XI.I {cmd = XC.Jmp, src = XO.Label {id = label, ty = T.Voidt}, dest = XO.OpVoid}]
        | J.If {line, value, truee, falsee} =>
          let val newValue = transOperand value
          in [XI.I {cmd = XC.Cmp, src = XO.IntNum (Intl.fromInt 0), dest = newValue},
              XI.I {cmd = XC.Jne, src = XO.Label {id = truee, ty = T.Voidt}, dest = XO.OpVoid},
              XI.I {cmd = XC.Jmp, src = XO.Label {id = falsee, ty = T.Voidt}, dest = XO.OpVoid}]
          end
        | J.Return {line, value = O.OpVoid} => []
        | J.Return {line, value} =>
          let val newValue = transOperand value
          in  [XI.I {cmd = XC.Mov, src = newValue, dest = XO.Reg {reg = XR.eax, ty = rettype}}]
          end 
  
  fun transStms (stms, transfer, exit, rettype) = 
      let val ins1 = List.concat (List.map transStm stms)
          val ins2 = transTransfer (transfer, exit, rettype)
          val ins = ins1 @ ins2
      in  ins
      end
  
  fun transBlock (b, exit, rettype) =
      case b
       of K.T {name, prop, stms, transfer, successors} =>
          let val newIns = transStms (stms, transfer, exit, rettype)
              val newSucc = successors
              val new = XK.T {name = name,
                              prop = prop,
                              ins = newIns,
                              successors = newSucc}
          in  new
          end
  
  fun transBlocks (bs, exit, rettype) = List.map (fn b => transBlock (b, exit, rettype)) bs
  

  
  fun setLocals l =
      let val localSize = 4
          val initSize = ~16   (* there are 3 callee-saved registers *)
          fun doit (loc, index) =
              case loc
               of [] => ()
                | {id, ty, loc} :: xs => 
                  (setLocal (id, SOME (XO.Rmem {off = Intl.fromInt index, reg = XR.ebp, ty = ty}));
                   doit (xs, index - localSize))
          val _ = doit (l, initSize)
      in  ()
      end
      
  fun setArgs l =
      let fun doit l =
              case l
               of [] => ()
                | {id, loc, ty} :: xs =>
                  let val off = case loc
                                 of L.InStack i => i
                                  | _ => raise Fail "compiler bug"
                      val _ = setLocal (id, SOME (XO.Rmem {off = off, reg = XR.ebp, ty = ty}))
                  in  doit xs
                  end
          val _ = doit l
      in  ()
      end    
      
  fun addPrologEpilog (blocks, start, exit, prolog, epilog) =
      case blocks
       of [] => []
        | x :: xs => 
          if Id.equals (XK.name x, start)
          then XK.addInsHead (x, prolog) :: addPrologEpilog (xs, start, exit, prolog, epilog)   
          else if Id.equals (XK.name x, exit)
               then XK.addInsTail (x, epilog) :: addPrologEpilog (xs, start, exit, prolog, epilog)
               else x :: addPrologEpilog (xs, start, exit, prolog, epilog)       
   
  fun transFunc f = 
      case f
       of F.T {name, exit, rettype, args, locals, stackSize, blocks, pre, post} =>
          let val _ = setLocals locals
              val _ = setArgs args
              val newBlocks = transBlocks (blocks, exit, rettype)
              val size = (List.length locals) * 4
              val prolog = [XI.I {cmd = XC.Prolog, src = XO.IntNum (Intl.fromInt size), dest = XO.OpVoid}]
              val epilog = [XI.I {cmd = XC.Epilog, src = XO.IntNum (Intl.fromInt size), dest = XO.OpVoid}]
              val newBlocks = addPrologEpilog (newBlocks, name, exit, prolog, epilog)
              val new = XF.T {name = name,
                              exit = exit,
                              rettype = rettype,
                              args = List.map (fn {id, loc, ty} => {id = id, ty = ty}) args,
                              locals = List.map (fn {id, loc, ty} => {id = id, ty = ty}) locals,
                              blocks = newBlocks,
                              pre = XO.True,
                              post = XO.True}
              val _ = destroyLocal ()
          in  new
          end
              
  fun transFuncs funcs = List.map transFunc funcs
  
  fun transProg p =
      case p
       of P.T {structs,
                gvars,
                funcs} =>
          let val new = XP.T {structs = [],
                              gvars = gvars,
                              funcs = transFuncs funcs}
          in  new
          end
  

  fun trans p = 
      let val _ = debugPrint "to x86 assembly code translation starting\n"
          val new = transProg p
          val _ = debugPrint "to x86 assembly code translation finished\n"
      in  new
      end
end
